﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace Kaesoft.Caja.Views
{
    /// <summary>
    /// Class Util.
    /// </summary>
    public static class Util
    {
        /// <summary>
        /// Obteners the application setting.
        /// </summary>
        /// <param name="appSettingKey">The application setting key.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns>System.String.</returns>
        /// <exception cref="System.Exception"></exception>
        public static string ObtenerAppSetting(string appSettingKey, string defaultValue)
        {
            string appSettingValue = ConfigurationManager.AppSettings[appSettingKey];

            if (appSettingValue == null)
            {
                if (defaultValue == null)
                    throw new Exception(String.Format(CultureInfo.InvariantCulture, "Clave de aplicación no registrada", appSettingKey));
                return defaultValue;
            }

            return appSettingValue;
        }

        /// <summary>
        /// Gets the enum values.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns>``0[][].</returns>
        /// <exception cref="System.ArgumentException">Type ' + type.Name + ' is not an enum</exception>
        public static T[] GetEnumValues<T>()
        {
            var type = typeof(T);
            if (!type.IsEnum)
                throw new ArgumentException("Type '" + type.Name + "' is not an enum");

            return (
              from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
              where field.IsLiteral
              select (T)field.GetValue(null)
            ).ToArray();
        }

        /// <summary>
        /// Gets the enum strings.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns>System.String[][].</returns>
        /// <exception cref="System.ArgumentException">Type ' + type.Name + ' is not an enum</exception>
        public static string[] GetEnumStrings<T>()
        {
            var type = typeof(T);
            if (!type.IsEnum)
                throw new ArgumentException("Type '" + type.Name + "' is not an enum");

            return (
              from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
              where field.IsLiteral
              select field.Name
            ).ToArray();
        }
    }

    /// <summary>
    /// Clase que simula ConfigurationManager para leer settings de aplicacion
    /// </summary>
    public static class ConfigurationManager
    {
        /// <summary>
        /// Gets the application settings.
        /// </summary>
        /// <value>The application settings.</value>
        public static AppSettings AppSettings
        {
            get;
            private set;
        }

        /// <summary>
        /// Initializes static members of the <see cref="ConfigurationManager"/> class.
        /// </summary>
        static ConfigurationManager()
        {
            AppSettings appSettings = new AppSettings();

            XmlReaderSettings settings = new XmlReaderSettings();
            //settings.XmlResolver = new XmlXapResolver();
            XmlReader reader = XmlReader.Create("ServiceReferences.ClientConfig");
            reader.MoveToContent();
            reader.ReadToDescendant("appSettings");
            reader.ReadToDescendant("add");
            do
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "add")
                {
                    appSettings.Add(new KeyValuePair<string, string>(reader.GetAttribute("key"), reader.GetAttribute("value")));
                }
                else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "appSettings")
                {
                    break;
                }
            } while (reader.Read());
            AppSettings = appSettings;
        }

    }

    /// <summary>
    /// Configuraciones de aplicacion
    /// </summary>
    public class AppSettings
    {
        /// <summary>
        /// Gets the <see cref="System.String"/> with the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>System.String.</returns>
        public string this[string key]
        {
            get
            {
                if (_settings.ContainsKey(key)) return _settings[key];
                return null;
            }
        }

        /// <summary>
        /// The _settings
        /// </summary>
        private IDictionary<string, string> _settings;

        /// <summary>
        /// Initializes a new instance of the <see cref="AppSettings"/> class.
        /// </summary>
        public AppSettings()
        {
            _settings = new Dictionary<string, string>();
        }

        /// <summary>
        /// Adds the specified settings.
        /// </summary>
        /// <param name="settings">The settings.</param>
        public void Add(KeyValuePair<string, string> settings)
        {
            _settings.Add(settings);
        }


    }

    /// <summary>
    /// Class GenericObjects.
    /// </summary>
    public static class GenericObjects
    {
        /// <summary>
        /// Deserializes the specified XML.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml">The XML.</param>
        /// <returns>``0.</returns>
        public static T Deserialize<T>(string xml)
        {
            using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(xml)))
            {
                var serializer = new XmlSerializer(typeof(T));
                T theObject = (T)serializer.Deserialize(stream);
                return theObject;
            }
        }
    }
}
